package com.cc.blog.web.service.impl;

import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.cc.blog.admin.mapper.ArticleMapper;
import com.cc.blog.admin.mapper.ArticleTagRelMapper;
import com.cc.blog.admin.mapper.TagMapper;
import com.cc.blog.admin.model.ArticleDO;
import com.cc.blog.admin.model.ArticleTagRelDO;
import com.cc.blog.admin.model.TagDO;
import com.cc.blog.common.enums.CodeEnum;
import com.cc.blog.common.exception.BusinessException;
import com.cc.blog.common.utils.PageResult;
import com.cc.blog.common.utils.Result;
import com.cc.blog.web.convert.ArticleConvert;
import com.cc.blog.web.domain.dto.FindTagArticlePageListReqDTO;
import com.cc.blog.web.domain.dto.FindTagListReqDTO;
import com.cc.blog.web.domain.vo.FindTagArticlePageListRspVO;
import com.cc.blog.web.domain.vo.FindTagListRspVO;
import com.cc.blog.web.service.TagService;
import com.google.common.collect.Lists;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * @Author cc
 * @Date 2024/7/12 10:54
 */
@Service
@Slf4j
@AllArgsConstructor
public class TagServiceImpl implements TagService {

    private final TagMapper tagMapper;
    private final ArticleMapper articleMapper;
    private final ArticleTagRelMapper articleTagRelMapper;

    @Override
    public Result findTagList(FindTagListReqDTO findTagListReqDTO) {
        Long size = findTagListReqDTO.getSize();

        List<TagDO> tagDOS = null;
        // 如果接口入参中未指定 size
        if (Objects.isNull(size) || size == 0) {
            // 查询所有分类
            tagDOS = tagMapper.selectList(Wrappers.emptyWrapper());
        } else {
            // 否则查询指定的数量
            tagDOS = tagMapper.selectByLimit(size);
        }
        // DO 转 VO
        List<FindTagListRspVO> vos = null;
        if (!CollectionUtils.isEmpty(tagDOS)) {
            vos = tagDOS.stream()
                    .map(tagDO -> FindTagListRspVO.builder()
                            .id(tagDO.getId())
                            .name(tagDO.getName())
                            .articlesTotal(tagDO.getArticlesTotal())
                            .build())
                    .collect(Collectors.toList());
        }
        return Result.success(vos);
    }

    @Override
    public Result findTagPageList(FindTagArticlePageListReqDTO findTagArticlePageListReqDTO) {
        Long current = findTagArticlePageListReqDTO.getCurrent();
        Long size = findTagArticlePageListReqDTO.getSize();
        // 标签 ID
        Long tagId = findTagArticlePageListReqDTO.getId();
        // 判断该标签是否存在
        TagDO tagDO = tagMapper.selectById(tagId);
        if (Objects.isNull(tagDO)) {
            log.warn("==> 该标签不存在, tagId: {}", tagId);
            throw new BusinessException(CodeEnum.TAG_NOT_EXISTED);
        }
        Page page = new Page<>(current, size);
        // 先查询该标签下所有关联的文章 ID
        List<ArticleTagRelDO> articleTagRelDOS = articleTagRelMapper.selectList(Wrappers.<ArticleTagRelDO>lambdaQuery().eq(ArticleTagRelDO::getTagId,tagId));
        // 若该标签下未发布任何文章
        if (CollectionUtils.isEmpty(articleTagRelDOS)) {
            log.info("==> 该标签下还未发布任何文章, tagId: {}", tagId);
            return PageResult.success(page, Lists.newArrayList());
        }
        // 提取所有文章 ID
        List<Long> articleIds = articleTagRelDOS.stream().map(ArticleTagRelDO::getArticleId).collect(Collectors.toList());
        // 根据文章 ID 集合查询文章分页数据
        Page<ArticleDO> ipage = articleMapper.selectPage(page, Wrappers.<ArticleDO>lambdaQuery().in(ArticleDO::getId, articleIds).orderByDesc(ArticleDO::getCreateTime));
        List<ArticleDO> articleDOS = ipage.getRecords();
        // DO 转 VO
        List<FindTagArticlePageListRspVO> vos = null;
        if (!CollectionUtils.isEmpty(articleDOS)) {
            vos = articleDOS.stream()
                    .map(ArticleConvert.INSTANCE::convertDO2TagArticleVO)
                    .collect(Collectors.toList());
        }
        return PageResult.success(page, vos);
    }
}
